package grails.company

import grails.converters.JSON
import grails.test.mixin.*
import grails.test.mixin.domain.DomainClassUnitTestMixin
import org.junit.Before

/**
 * See the API for {@link grails.test.mixin.web.ControllerUnitTestMixin} for usage instructions
 */
@TestFor(DepartmentController)
@Mock([Organization, Department])
class DepartmentControllerTests {

    Organization o
    Department d

    @Before
    void setUp() {
        o = new Organization(title: 'ACME', description: 'desc').save()
        d = new Department(title: 'Cartoons', description: 'desc1', organization: o).save()
        new Department(title: 'Cinema', description: 'desc2', organization: o).save()
        params.data = [:]
    }

    private void assertResponseSuccess(boolean success = true) {
        assertNotNull response.contentAsString
        def json = JSON.parse(response.contentAsString)
        assertNotNull json
        assertEquals(json.success, success)
    }

    private void assertDepartment(def json, Department d) {
        assertNotNull json
        assertNotNull d
        assertNotNull d.organization
        assertEquals(json.title, d.title)
        assertEquals(json.description, d.description)
        assertEquals(json.parentId, d.organization.id)
    }

    void testListEmpty() {
        Department.metaClass.static.list = {-> []}

        controller.list()

        assertResponseSuccess(false)
    }

    void testListNonEmpty() {
        controller.list()

        assertResponseSuccess()
        def json = JSON.parse(response.contentAsString)
        assertDepartment(json.data[0], Department.findByTitle('Cartoons'))
        assertDepartment(json.data[1], Department.findByTitle('Cinema'))
    }

    void testViewNoIdSet() {
        controller.view()

        assertResponseSuccess()
        def json = JSON.parse(response.contentAsString)
        assertDepartment(json.data[0], Department.findByTitle('Cartoons'))
        assertDepartment(json.data[1], Department.findByTitle('Cinema'))
    }

    void testViewInvalidIdSet() {
        params.data.id = -1

        controller.view()

        assertResponseSuccess(false)
    }

    void testViewValidIdSet() {
        params.data.id = d.id

        controller.view()

        assertResponseSuccess()
        def json = JSON.parse(response.contentAsString)
        assertDepartment(json.data, d)
    }

    void testUpdateNoIdSet() {
        controller.update()

        assertResponseSuccess(false)
    }

    void testUpdateNoTitleSet() {
        params.data.id = d.id

        controller.update()

        assertResponseSuccess(false)
    }

    void testUpdateInvalidIdSet() {
        params.data.id = -1

        controller.update()

        assertResponseSuccess(false)
    }

    void testUpdateValidate() {
        Department.metaClass.validate = {->false}
        params.data.id = d.id
        params.data.title = 'Cinema'

        controller.update()

        assertResponseSuccess(false)
    }

    void testUpdateValidSet() {
        params.data.id = d.id
        params.data.title = 'Cinema'

        controller.update()


        assertResponseSuccess()
        def json = JSON.parse(response.contentAsString)
        assertNotNull Department.findByTitle(params.data.title)
    }

    void testDeleteNoIdSet() {
        controller.delete()

        assertResponseSuccess(false)
    }

    void testDeleteInvalidIdSet() {
        params.data.id = -1

        controller.delete()

        assertResponseSuccess(false)
    }

    void testDeleteValidIdSet() {
        params.data.id = Department.findByTitle('Cartoons').id

        controller.delete()

        assertResponseSuccess()
        assertNull Department.findByTitle('Cartoons');
    }

    void testCreateNoParentIdSet() {
        controller.create()

        assertResponseSuccess(false)
    }

    void testCreateInvalidParentIdSet() {
        params.data.parentId = -1
        params.data.title = 'NewOrganizationTitle'

        controller.create()

        assertResponseSuccess(false)
    }

    void testCreateValidate() {
        Department.metaClass.validate = {-> false }
        params.data.parentId = o.id
        params.data.title = 'NewOrganizationTitle'

        controller.create()

        assertResponseSuccess(false)
    }

    void testCreateSave() {
        Department.metaClass.save = {-> false }
        params.data.title = 'NewOrganizationTitle'
        params.data.parentId = o.id

        controller.create()

        assertResponseSuccess(false)
    }

    void testCreateValid() {
        params.data.title = 'NewOrganizationTitle'
        params.data.description = 'NewDescription'
        params.data.parentId = o.id

        controller.create()

        assertResponseSuccess()
        def dep = Department.findByTitle(params.data.title)
        assertDepartment(params.data, dep)
        def json = JSON.parse(response.contentAsString)
        assertDepartment(json.data, dep)
        assertTrue o.departments.contains(dep)
    }
}
